package cn.xyt.net;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.tom.mvc.ext.BeanFactory;
import cn.tom.protocol.http.HttpMessage;
import cn.tom.protocol.http.HttpMessageAdaptor;
import cn.tom.transport.Messager.MessageHandler;
import cn.tom.transport.Session;
import cn.tom.transport.nio.NioServer;
import cn.xyt.dto.Form;
import cn.xyt.dto.SystemProperty;
import cn.xyt.service.CmdService;
import cn.xyt.service.RpcService;
import cn.xyt.util.DeviceCache;
import cn.xyt.util.HttpUtil;
import cn.xyt.util.PullSession;
import cn.xyt.util.WebRequestCache;
import io.netty.channel.Channel;
/**
 * 开放内网 rpc 接口调用
 * @author tomsun
 */
@Service
public class RpcController {
	
	@Resource
	CmdService cmdService;
	
	@Resource
	RpcService rpcService;
	
	@Autowired
	private SystemProperty property;
	
	public static Map<Integer, Object[]> cmds = new HashMap<>();

	static{
		try{
			
			cmds.put(0xA7, new Object []{0xA7, CmdService.class.getMethod("cmd_A7", Form.class)}); //机主号码绑定/解绑
			cmds.put(0xD6, new Object []{0xD6, CmdService.class.getMethod("cmd_D6", Form.class)}); //机主号码绑定/解绑
			cmds.put(0xA5, new Object []{0xA5, CmdService.class.getMethod("cmd_A5", Form.class)}); //机主号码绑定/解绑
			
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	
	/**
	 * http://127.0.0.1:7070/sendcmd?cmd=11&deviceid=123456&code=2,1
	 * @param res
	 * @param form
	 */
	public void sendCmd(HttpMessage msg, Session sess){
		Form form = new Form();
		form.setCmd(msg.getHeadOrParam("cmds"));
		form.setCode(msg.getHeadOrParam("code"));
		form.setDeviceid(msg.getHeadOrParam("deviceid"));
		String cmd = form.getCmd();
		int _cmd = Integer.parseInt(cmd, 16);
		Object [] obj = cmds.get(_cmd);
		/*返回命令msgid*/
		int resp_msgid = (int) obj[0] ; 
		form.setResp_cmd(Integer.toHexString(resp_msgid));
		/*发送消息方法调用*/
		Method me = (Method) obj[1];
		try{
			Map<String, Object> resp =(Map<String, Object>) me.invoke(cmdService, form);  //TODO  改成异步的
			if("001".equals(resp.get("state"))){
				msg.setJsonBody(HttpUtil.serialize(resp));
				msg.setStatus("200");  
				sess.write(msg);
				return;
			}
			WebRequestCache.set((String)resp.get("data"), new PullSession(sess, msg));
		}catch(Exception e){
			cmdService.logger.error(e.getMessage(), e);
		}
	}
	
	/**
	 * 异步发送
	 * @param msg
	 * @param sess
	 */
	public void sendCmdAsync(HttpMessage msg, Session sess){
		Form form = new Form();
		form.setCmd(msg.getHeadOrParam("cmds"));
		form.setCode(msg.getHeadOrParam("code"));
		form.setDeviceid(msg.getHeadOrParam("deviceid"));
		String cmd = form.getCmd();
		int _cmd = Integer.parseInt(cmd, 16);
		Object [] obj = cmds.get(_cmd);
		/*返回命令msgid*/
		int resp_msgid = (int) obj[0] ; 
		form.setResp_cmd(Integer.toHexString(resp_msgid));
		/*发送消息方法调用*/
		Method me = (Method) obj[1];
		try{
			Map<String, Object> resp =(Map<String, Object>) me.invoke(cmdService, form);  //TODO  改成异步的
			if("001".equals(resp.get("state"))){
				msg.setJsonBody(HttpUtil.serialize(resp));
				msg.setStatus("200");  
				sess.write(msg);
				return;
			}
			WebRequestCache.set((String)resp.get("data"), new PullSession(sess, msg));
		}catch(Exception e){
			cmdService.logger.error(e.getMessage(), e);
		}
	}

	
	public void get(HttpMessage msg, Session sess){ 
		long a  = System.currentTimeMillis();
		String module = msg.getMeta().getParam("module");
		HttpMessage res = rpcService.invoke(msg, sess);
		if(res == null) return;
		rpcService.logger.info("rpcService.module:"+ module +" last: "+ (System.currentTimeMillis()-a));
		sess.write(res);
	}
	
	public void post(HttpMessage msg, Session sess){ 
		long a  = System.currentTimeMillis();
		String module = msg.getMeta().getParam("module");
		HttpMessage res = rpcService.invoke(msg, sess);
		if(res == null) return;
		rpcService.logger.info("rpcService.module:"+ module +" last: "+ (System.currentTimeMillis()-a));
		sess.write(res);
	}
	
	
	/**
	 *  NIO rpc Server
	 * @throws IOException
	 */
	@PostConstruct
	public void startServer() throws IOException{
		NioServer server = new NioServer("0.0.0.0", property.getHttpMsgPort());
		HttpMessageAdaptor adaptorServer = new HttpMessageAdaptor();
		BeanFactory.singletons.put("adaptorServer", adaptorServer);
		adaptorServer.registerHandler("get", new MessageHandler<HttpMessage>() {
			@Override
			public void handleMessage(HttpMessage msg, Session sess) throws IOException {
				get(msg, sess);
			}

		});
		
		adaptorServer.registerHandler("sendcmd", new MessageHandler<HttpMessage>() {
			@Override
			public void handleMessage(HttpMessage msg, Session sess) throws IOException {
				sendCmdAsync(msg, sess);
			}
		});
		
		server.setIoAdaptor(adaptorServer);
		server.start();
	}
	
	

}
